/*
    *@brief              :对文件加锁或者解锁，但是 flock()函数只能产生建议性锁

    *@param[fd]          :文件描述符，指定需要加锁的文件。

    *@param[operation]  :LOCK_SH： 在 fd 引用的文件上放置一把共享锁。 所谓共享，指的便是多个进程可以拥有对同一个文件的共享锁，该共享锁可被多个进程同时拥有。
                        -LOCK_EX： 在 fd 引用的文件上放置一把排它锁（或叫互斥锁） 。 所谓互斥，指的便是互斥锁只能同时被一个进程所拥有。
                        -LOCK_UN： 解除文件锁定状态，解锁、释放锁。除了以上三个标志外，还有一个标志：
                        -LOCK_NB： 表示以非阻塞方式获取锁。默认情况下，调用 flock()无法获取到文件锁时会阻塞、 直到其它进程释放锁为止， 如果不想让程序被阻塞，
                            可以指定 LOCK_NB 标志， 如果无法获取到锁应立刻返回（错误返回，并将 errno 设置为 EWOULDBLOCK） ，
                            通常与 LOCK_SH 或 LOCK_EX一起使用，通过位或运算符组合在一起。

    *@return            :成功将返回 0；失败返回-1、并会设置 errno，

    *@others            :需要注意的是，同一个文件不会同时具有共享锁和互斥锁
*/

// int flock(int fd, int operation);

//使用 flock() 对文件加锁 / 解锁

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/file.h>
#include <signal.h>

static int fd = -1; //文件描述符

/* 信号处理函数 */
static void sigint_handler(int sig)
{
    if (SIGINT != sig)
        return;

    /* 解锁 */
    flock(fd, LOCK_UN);
    close(fd);
    printf("进程 1: 文件已解锁!\n");
    
}

int main(int argc, char *argv[])
{
    if (2 != argc)
    {
        fprintf(stderr, "usage: %s <file>\n", argv[0]);
        exit(-1);
    }

    /* 打开文件 */
    fd = open(argv[1], O_WRONLY);
    if (-1 == fd)
    {
        perror("open error");
        exit(-1);
    }

    /* 以非阻塞方式对文件加锁(排它锁) */
    if (-1 == flock(fd, LOCK_EX | LOCK_NB))
    {
        perror("进程 1: 文件加锁失败");
        exit(-1);
    }

    printf("进程 1: 文件加锁成功!\n");

    /* 为 SIGINT 信号注册处理函数 */
    signal(SIGINT, sigint_handler);

    for (;;)
        sleep(1);
}

//加锁成功之后，程序进入了 for 死循环，一直持有锁；此时我们可以执行另一个程序，
